{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# !wget http://baidudeeplearning.bj.bcebos.com/image_contest_level_1.tar.gz\n",
    "# !tar -zxf image_contest_level_1.tar.gz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "/home/husein/.local/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import os\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "from skimage.transform import resize as imresize\n",
    "import cv2\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100000"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "directory = 'image_contest_level_1/'\n",
    "images = ['%d.png'%(d) for d in range(100000)]\n",
    "with open(directory+'labels.txt','r') as fopen:\n",
    "    labels = [i.split()[0] for i in list(filter(None,fopen.read().split('\\n')))]\n",
    "len(images)\n",
    "len(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXAAAACeCAYAAAArIFF5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO29d5xlV3Xn+903161cXdVZHaRWRpaQBEhIAoFNBhkzhgHzMBgYbI/NGNszhOE94zh+eN6z8XzGHoMBEwYLY7KxQICEDLKFIi0JhVZoutW5q7pyuFU37PljrXVuqFtVt3Jdev8+n/rcuuGcs88+++zz22v91lrOe09AQEBAQPMhtt4NCAgICAhYGsIEHhAQENCkCBN4QEBAQJMiTOABAQEBTYowgQcEBAQ0KcIEHhAQENCkCBN4QFPBOfenzrn3rOL+tzjnHnPOpVfrGAEBK4UwgQc0DZxzfcAvAx+t893vOee8c+7naj6/0Tn3tprP9jjnbnHODTnnTjrn/qdzLgHgvT8FfA941xLa55xzf+ycO+acG3HO3eGcu3Sx+wkIaBRhAg9oJrwNuMV7P1X5oXPuPOD1wImKz17rnHtXxfvXOed+Vd/+NXAa2AZcAbwQ+I8Vu/wc8KvUgU7+h+Zo3+uBtwM3AD3AXcBnGzy3gIBFI0zgAc2EVwD/UufzvwLeB8xUfPY1oAD8N+A9wHnA3+l3e4EveO9z3vuTwLeASqZ8N3Cuc273Itu3F7jTe3/Qe18E/jdwySL3ERDQMMIEHtBMuAw4UPmBc+71wLT3/pY6v6/ME1GqeP8R4I3OuaxzbgfyYPhWtJH3BeAp4PJFtu/zwHnOuQucc0ngrZX7DQhYaSTWuwEBAYtAFzBmb5xz7QjDfkmd374WSAEfBHYDo4h546PA9xEb9ygQBz4NfLVm+zE93mJwArgTecgUgSPAixe5j4CAhhEYeEAzYQhor3j/+8BnvfeHan/ovf+K9/6jKOv23n/Ze/9R51wMYcVfBlqBXqAb+HDNLtqBYQDn3C8554adc8PAQ8Aue69/u3Sb3wOeA5wDZIA/AG53zmWXf+oBAbPhQjbCgGaBc+67wN957z+n7/cDOxFbN0AfMAJ82HtfOyHbPnqBfqDLez+in70W+GPv/bP0fQJh5xd77w/XbL8HuMN7v6fOvr8BfMd7/5cVnw0DP+e9v2+Jpx0QMCcCAw9oJtyCKEYMPws8C1GSXAEcR9QjfzXXDrz3A8BPgF93ziWcc12Irfqhip89FzhUO3k3gHuB16uWPOacewuQROzpAQErjmADD2gmfAbY75xr8d5Pee/PVH7pnCsCQ9778QX28zrEkfk+xFZ9O/DbFd+/GfibJbTvw8BmYD9innkK+Hfe++El7CsgYEEEE0pAU8E599+A0977j6zS/jcjUsVne+9zq3GMgICVQpjAAwICApoUwQYeEBAQ0KRY1gTunHu5c+6Ac+4p59z7V6pRAQEBAQELY8kmFOdcHHgCCaI4injg3+S9f3TlmhcQEBAQMBeWo0J5LvCU9/4ggHPu88DPA3NO4L09cb/nnOQyDhkQsHQ8PNILgIsLaXlW25n5fh6wRnjiofpxThf8zOQat2Tj4v6Hpge89321ny9nAt+BhAobjgLPq/2RZoR7F8CuHQnuufWcZRwyIGDp2HvLOwFId0wDcM/1IVHgRsDLtl9R9/Nbb92/xi3ZuIhve6puTMKq68C99x8DPgZw9eWZIHkJWHN8e1JWfX3bRgCYmpH3v3r0WgA+uPU77Eq0rU/jznLcPz3DefdmALjz5isBuP5ND0TfAVyVTq1P45oAy3FiHkNyPhh26mcBAQEBAWuA5TDwe4HznXN7kYn7jcAvrUirfkqQ90UGilW1B0g6B0BvvHU9mnRWIuWKVe8nxoTx9eeEdfcXU+wKMcnrgqvSKej9PgDvePf3Z38XMC+WPGy99wXn3G8CtyIpOT/pvX9kxVoWEBAQEDAvlsU7NIl+vUT6ZzVOFycAOFmM84PJiwF4bGI7AL/R9z0AeuPr07azEdmYOC0zCU1aqJ6YgSlh4Dkf6Pd6IjDtpSOM3BXASEnMJANFWarvn5bJ+q+fuZH+cTGVbO8YBeBUj0waF1Na41aevWh1MnGf39kPwLF+qdPQPyrX4lC+j/OTzwCwOZi2ApoIIZQ+ICAgoEmx4Rn4eKl+Qri2WGaNWzI3BpV5/82ZGwC4/dj5AIyOZSlMSRcPJgv1Nw5YdfTFZbWzJS2roHQmD0BuUpbuH3/meq44//MAbA6mrYAmQmDgAQEBAU2KDc/A+4vCXL82/iwAnp99EoBzExPrLsXLe2HeR4piS31kZBsAQ0Py3ufKdK5QlGfljLfPgg18rZB10ucvaJeC9t9KiWN5alhWccOTLRwqdAOwNyEsPRsLjrWAjY/AwAMCAgKaFBuWgZvt+3ChA4A7Bi4E4Lte2NMHdv0zIHK9xTBxC8+txVKkTBak88CUrA4OnekBwM/oc7EicYD3btH7X2+sZF+tJ8xfsjsxBMC53ZLE6kejkkRpYirFjyb3AHBlSmoPBwY+G42Mh6KXleWQKrMmNdtpXu+FzpjTV7kmSRecDstBYOABAQEBTYoNy8Bzal/+3rgw7mdGRLubL8oT+7+7V/Cnu78CNB4Uc//0DJ8YeAEwO3GOhfMuhl32l6T7/vnkZdJmVTVQnM22nWuePF7GtObrq2Zj4QDbE3Jd/q+tPwTg8f4tAEyOp/nh4F4AbuqQDHjb1qF9GxWNjAeAfclipMh6cGYrAN8cknsjruP/guxJAC5KnwAg4/L0xWUlbWqhoMVvHIGBBwQEBDQpNgwDN9vZuJew5wP5FgCenpAc5uOTaQDyynIHs1OcKjYW1VjJIB79kDCCHkQLbGyiNpHOfLDIyydnhMGdGlPVyczcz8NEfOOrTmqZ1kr0laEysZetXMZK1Sx+a1wS+JudtAScqVnN9GkxhqUokDpjMqa2qy18V7e8Pj66jcNDokI5uEOKPuxO9Fdtc7ag0s59f24PAPvHdwGzx8O//r2Mh1f9hqxazhSL3DxwDQBPa/GMwQnxM8zMyDL5+6nzAOjMyljIF+PsbB8G4I92fR0IWvzFIDDwgICAgCbFhmHgJZVsHC/I6z8OPReAx85sBqAwnbAfAjAxs/jSbHfefGXEHgyRHW8RsJwn/9h/NQBTujqoZ/s2mA68GWBMeyX6ytREp4oFbpu8AICvnpQKLKPTokRoS2myqbho/n9pm9io8z7BZ48Jo8smhBn+2vY7ALgsJey5PSbjYjGRuX2a3KonLYw/kS4wrePrn85I267c/i0AOtfosllMQS3WSqVRufqy69/3yqMAjH12BwBZqqOJr/z3DwNECp5vHr+EE6fEV+Un9H5N6w2r94aNqAm0jFrMMz4l9893Nl2s3z4mxw828QXRPLNKQEBAQEAVNgwDN4x5YdZjeWFUkzl5OvuCPmv0Se69W3RU4/VvemCWB/0dS1CfnCwKezg12Q4Q5Tv5aYH1zXL6qpJ5A3xi8PncfkIY+KDqrws5udZer2k8Iyz09/tfI597RyEv1ziRlO8+UnwJADdteRCA17U/AUCLL4+BuJufl/TEZZ9v2ixM/9GBLQwPC8sbmhGbd39RznGtCj1M+7weV/qrLy4HXm0GXs/vYSuvsTPCvNvfIoW2+m/ZCZTHwxs3Sf99f/wiAI4f3sQeEYZx6mpp//QmuS6lbP0VBkUXqbc+9tj1AHy3tzLWA7JOxtJGyn+0UbBhZp7yElJu5qmi3tymvrNXdWIl4qVZlVbmQjTh9H5/WVU/zHnZXxTH6siUDqh5TCeGqemUbiuBSQNFSV+63ukAKmF90d/9IwCueddTVd9vj8vNPlnxvKwNeDFn9GBJJqKbR8TMtH94ZzRx5yd0G7um2n/FcRmOU+MVw1K7tpCQz54qinPs+yl5GPQlxgA4P3UagN0JT6eb3/FojsmtcQmbP7f7TBTUYw/l1c4Rbjnj+9W0ZqH8/Rq4dllazBe7E4sPVlsK6pnNrv5NGQdXtMlYverdX6zaxvpo/4hM7Pv+vkByQMxS2/KaqvfVC5s6/ZQ8pKam5LocUHHAX8RfCsB7d34TkPQZsLHumfVGMKEEBAQENCk2DAMf1yXkA1PCrA6ObAJgZrKa4bmUMLz29HRUaQUac2guN/jEnJdfOP0cAMbGG5eYTU9JGz919PkAXHGeMKyNVJlnQFlhVh/rXzj5YgASTvp8045xANpjOS5PTc3eQQXMBHHf0G4ADvZvKjuibcXSSGyT/SavTjAdDw8cE9b3uDq5n7/tEAC/0vsDLkw2tuTu0xVFZzJHXB1muby0caKUtgM30MjFw5j3nxx7JQCHx4SBW8DLzjaR1v0/O8SMsNrjpNJsNrfJrPr++ZY675++We7ZLZNj0ZL5xDVq+oxJv7oWuXdcTL73JTWF5uKzxoGZJB86JoVR/rB4EwB/sPtrAGRcLphTFIGBBwQEBDQpNgwDN0Zyx5AkrTJ7qTm4zBaaSIlt9eLOU1GprEYZ+HJQ9KXIeWlsaZbzUu3zlGYzTEstOzYtzKS/aHa81Q3wMVZdi3p2xFN6Df7smVcA8MRJsfXH9bw+4aRgxRu33sNFyfr7nfLCavuLnXL8KTnOzGRqdpIv6y9zITTCzJWJTw8JA5tOSn9+NycsMO9j/KfNtwOwOzE/E+9RCeIrex7irqN7ACiV1obT2PW3sXRyQPorpgw1rsy10WC1paLSPwTVQVpzrVhtTD2aOxeA0X3Stp4DKU68TH0IW4Rxx3pkPPR2i6/i8l5xiP6oX1ZQ/Sc7oVDjQ9L35is5NChJ4j7RKo7W3+j73oLX9mxBYOABAQEBTYoNw8An1KN9JifMpDCjTTOSprbvzV1ih92aHomE/muFvLaxWKrPJGNpYR0lK+RQqU7R384U5LvVKuwwEKkb5NgH8uLR//awpLx9W+8PALEjtjhhOCa7M1Z4ekJYX35cvi+qvC+nyqBcKUl6DqnepKqJ7prYJ+814MqXXLm/bFGVlHNPZ6vtzEktP5fPJyLfwaw0BbbKMUY+Lkz8vlPn8KmE+BnerefaNgdNMfa2KT5OS1qYoqmFhkuy2hooHgdWRvlgSquhUo5jBQlPHzOZbLGcPgBgpri2zpFFJXHTtn7/jJQOLHXI9frJTUnsDGqZ9zVbDgFwSfZ41b7uyieYGJfrMOu+0fEypX6Pu09Kn/WlrubXuu8G5r62ZwvO8tMPCAgIaF5sGAY+C6Vqu5jZvntbhGG+qO3RqFTWWmDcT3OmKGHCkzVh/Ol2UcOY/dK0MaWJcvc6ZbFtyvR2aOkuWNlkSSMlacNHTv8cULY1ZhIaUOPVjrj5e+xOSEunS8KaIlY4Wa1vtyCqmCokzkudJski+95TtnUnZD/GvLd3jwBwfd/TADw7exgQJcgnj1wnbVLfgalExofVRzKtHETtpkNDbezPyjkf6pKVRE9sYXtpRln/6Jjs9+9PSAj/ZYtMWTwfjIHvn+7ic8efJ+czJezS5+U8vLp1hsalHcdUH366+MyGCSkfLEk/jszIq9Pr6VuK0bVtycrYOrdTimdc1CLpY29okdiC61rkWr+iu49PHZdr/ES/+Fxyupqya2vMfCIlnx+d6maya1VOrekQGHhAQEBAk2LDMPC4GrzaVcOLFUBwGmatduZNaWHgXbFp2tYg1We5tJvjcyerWZMxymxGWPVztkrE2vcPi/03NzG7e1+748FVaafZvvdPi3bWmPdAv0T2pbLSxmxSPPqfjF/Pb/XeAcCY2vY//oyEMpvd2WD22eFcub/nKjlmq6JrW4VpfTN+ie6k/BvTAne2ipb87ef8KwAvbhHmbQmqJn2RK/aJXv7+3DkA3HLmZ+Q8ZyTMe7qoeu1CebUwOCntvG3sUgDOX8BeuiU+TmdaQ/+9qEFOToiaol9t4RfX33RRGCnJNTg4s5eTY7L/vPV1TTSvhZfbNbni/M/PSrNqkcHTvtqP0r1K5crsXsh76ZPIFxQrX9xERpYQl20Wxv2urf8CwIVJWXHWJh/bmejnXNV3f7pNfBe3HJTrlitUJ4krqv8omiMCAgMPCAgIaFZsGAaedDVqjJoiwNmM2NTs6dseaywPynJhpd2+PnoVA1NiU7WIQqergs1toow5JyMpTjMpse3mqLC56un880lRg7xs3yMr2k5TBnzimDC2wWEtMqGfW0TrYS283JuZ4EBeol3PqNb45LCwdctNEUH3YbZ/UePUV88Ys8q4mgjGCp9GIi0sbXub2L6vTB8BYHM8W7VJi4NuZXdZdwiAEx1iEx6eFpZ9sCTnkB9VtlaCsQlpw4FxUeD0d8r1mqtMWl/c844ddwLwoSFJpDWqfoAj2kenk89oG5duh55Uonr36LnkzI8yhwjJ4gZGVaVyrNDBpanqPrXyZV8blzF1RUbaeLWmyV1pBl7UZdQDU3tk/3G9B+3axj1trXJ/vnnLXQA8W1fMbU6ubW2isc5YC/s0VfDPd0sE6COb5EodGNtmB5bD6HFmSglyfgOFMK8jFpzAnXPnAJ8BtiAL4Y957//SOdcD/AOwBzgEvMF7P7TUhtgFmSyoU0cvlk2SHTqBv65bqoZbEMZqw5yCeR+nf7Stqm1xlQ1aHuvkPMm1VjOQZ7yU42BBJuZT49LG4lS1JMsm8nxS+m1wOsvTMxKGfvMzkhqg1nRicOlqB6zUMFyk+arChGKZBd+49R7dnwav1JMmqnnAsvPd1C4mqLyOl2MjYvLIm0mn5KIHrCWmqq38U4veeCtbExK6vrNLXg+ekqRZtakPNmmAzUIZD+shFr36yOG9EHwFkalNgHWvBtL8cFheM90ywZ+bPACsvMTOTDWWwmJYk7lF92qixI5OeSibSTRbI1WtBzPHbYqJSagtOR3tD8Cr6UStqRwc2wTi74ySpy3levw0oJGzLgC/672/BLgG+A3n3CXA+4HbvPfnA7fp+4CAgICANcKCNNZ7fwI4of+POeceA3YAPw/cqD/7NHAH8L6lNiRnecBnykthaaFWs+6UdKF9MVketsWql9urhRkvz7gD41ui3NTGJpMqbdyZFdbWnagfXl65TbFGHrkSmPRF7hqXoIqZwvyXtKRytdHpDN/pFwejLdNnmU4UqRZhdr+6R8KsFxNAFZ2vI+oDMzF16bXsnscZbcyqzQnbO0dDqDerUyyl8sjK9AUmybNgmHyUGnbudm/XepxWpeegfj4wLiulJ/NC+fYmBoEys1wMLA/5azbt554Tu6rbXYs6BN2Y94eOiJnniTPSJpNAgqShuCH71KxtVwLmoM7E5PolbRxEKZ8dBXVsWjKwSS/3xkIpfgEyuoI1oUJax11Og7gstfS57Wc4U7L9bfxas6uJRa07nHN7gGcDdwNbdHIHOImYWOpt8y7n3H3Oufv6z6yN3TogICDgbEDDhmTnXBvwJeA93vtR58rMwXvvnXN1jXre+48BHwO4+vLMnIa/kjLdSJpUw0wKJXn6l1h5BlsP5YoyYlM+k2ulOFPNUNuz8ptXdItdNreArRXKNs1GQukrK4RXojbseaLkowIYhcIczh3t+cipWYyzp02CLCyAYi6YTLJPCyAsxpGXrMPWzYF3UG3wF6XEZtvTQH3LmHKOPUmpGh83W7IlxqpIjFRcRGIqY8ev7RNH2v4TIlOc0JSp903sBeDK9EkAds0ho5wPVkiiKzZJi65CxhexvflNnhkVR+7YoLyfSGniKL0FH+8TLtUXP7GiwT9pJ9dtT3IAgJakOlVt8VNykU/itvZLqn7baIpfgK1pGWfRilcRT8h5Ds+00BUzKeHyUkQ3Oxoa4c65JDJ5f857/2X9+JRzbpt+vw04vTpNDAgICAioh0ZUKA74BPCY9/7PK776OvBW4P/V168tpyGxWhmhMStl4gfHRM6V27I28qExLQn2vXEJ4RgYb43YqyljOjPCAqw01xmE7cyxGAHK7NOSJY2UhNF1VtiBa+sU1tampJHalK7mtaZ82fhUOqo7WprLDptUJYHZrNVO3Ej63qSm+k2oaoOYj449My3b/8MxKbc2sEXUIr/QISW8tsTFBppx8Ui6ZjAlRF5D+VtTmr628mematNjzxpbdVDJjgHSalfOaUrT+wbFZv2GrnsB2LXgHufGjI837Aux5Fo/zp0TnYdVcbfFm4Wan1Hp6N8elbS/F537xVnBP8uByRJNhZJW9ZXTVZbPx5ickLbdeWxv1bbv7pMUv/tUgRTTixR3sUhJYkq0h0ckGK2Yr+GXunrNFRPkdcV+tqpPDI2YUK4D3gI87Jzbr5/9V2Ti/oJz7h3AYeANq9PEgICAgIB6aESFcifMaXj+2ZVqSFzpRGRXs+PXhBgX18gGPqz206cnxD48MZWqSIeqZa9ah+tu6/3cbcxrmtwv918FwHN2fh2ATiUS90/PVFUIh3KhWWPitYWZ22OOzSlJ22l2+aLpvq0kXb46Red0LskPDol+uDiH3TymttVrN/9E9h0F5zTCwGXbDg1RPxYjCsgoKmO0wKH7UlJ2bUAL4b6882EArkwPckjjAvbn5Dc7kqIC+frgswE4NdI+69i2QsrqWMosot1WKNtWUZbIazJvaWZXpoBANEYWkIObNv9vH7suatN0zoKAqvdRmJSxZSkPxGa+8ioNU4tkNQAnpkqxYgFK2oZxVYk81ir2+Ic7JShne0JWnG0uTS3Mxn90TDJVmZrIztPiB7KJPD0x8w8FG3hAQEBAQBNiA4XSy9M1spmafFjZVLfqc+MNVcJdOsweN6a69MmCqjtyZfaWaZWnf16VMcYGzhQXtoE3AmPaPTUFdSMbeA0yLs6r2x8CYGCbsNjbilJibFjb7WtWLqXpeLS68dP1Gbh5/WsxXlq4qKyVu4tYWqpIKV9d1Hha7cuPnhCWNtgtfoHepGgzJkppnpqW7x6f2ArAk8OS5vXMmPR1bszswWW9eUwLRWxp0VXJIhi42Zkt6tRCi8fVFm1qqbXSH1sEby4Xn+UXmnUr6Od51YtP+BSTJfHPzJV8bClI6rnvapXeeapVolbHcq1ltZOyZ9PR3zsuq71WtZ/vSci2sYqTeGRadOy16Yxt6Fr06i/0PhCphs52BAYeEBAQ0KTYMAzcEHc1DFzzIWQTFr23NravSY0ks3wavkJfbAqF67ueBKA1Jt/V2k/rwaI3X9d3P1DWH5vufKyU5Wd+8VEAHvqiaGmNeb9jDvVJWyzDXmW6r+oUTfrd/XsAqG+lF/haL/+sH8h5HZsSm+TXxy4HpJjGOXFhyb1xsXXWJk7q0WRjl3ZIrNeB1s2MG9O31K8aYVdQZjw4IQz8m8flvL9RelbEJqfzWs5NU/kW65WtQ0rvtbdJTo1ru6RowKZ44ysi0xe3parzcZgaxAosDBSf0fNfvM56R2I0YvjDLdJPc0XBVpWhm4t51yCvEag/mtzD89IyzrLLuF9sbPYXZeweLAjjHsnPE12p12ViVNj0Pz0lCbfu6hB1ys52GZkXtp3ikVGxj5vte66cPFnts03x8SrV1tmMwMADAgICmhQbhoFbdjmzKxvLMLvXnqxEDSZXWYQy7oV5Wfk0K21F0UW66HbNjHhJ5hhQTqDfp/rlrhZhLEMtbbOYlbF30xvn1eb+lNra9+d28Yt9knHxt9/97apt59N9m43zHC3VtqtdbIzGaieVCUXFgQtutka8BkVlv6emZBVyV0HsmA+P7eDqzkMAvKbtx4AoYaAcpdmp7XlR22MA/FvHuRxUjXDJV7Nna9PEUEvVK5QZsMFUIfWYN0CmbZort0jmwEvTcn0WU3qvKybX58puSXH75AmJFp3RDIc3n3iufL9Hvl9KqbW+eCnKK/NHI68EYHouBm5YXddPXViRkIOqBPrUwI0APDYsfolhLZwxqel7q9potnBdKU3r6zH1WZxuFV/N/aWyor4wVe0jqS3Bl4qHVBy12DATuCFfU43bRek75XVhN9QSj6t5v49qXqCbT8mNOl3hvExqVZvzOyWM28wISddWta9XbZVJ7X8ev3HB41oe7///+MsA6ElNckP2CWBxlcINnTqR/vpWCZz4XFLSod7+E0l2NT1T4XxcYFIoqcnj0EkJourqlBs6GS+RK8rQuWdYlsQf3HELQBQ4Yg+U3fZAaR3iRFZkg5MFfZjUVB+vDIOPmjhXdXbbRs0jaXUs7+geoSUu5jZzSNYGA80HC+fflzkl+83IviYG5EE4ZBK9ZVTq2RxvjdISWJqCaVZAnqhkx4QAF2eOk1lCTnAzmdjE/YeHb5L3AxpMp87nWQ/TRrpZr3GUv32+7XTiNjlrOmFpmws0s/Gg0RQZjaB5eyEgICDgLMeGYeBFfZaUaoJgSsrATk4Le7MAm7mqqywVA0VxfN06LjUXHzkpR7AwZeKe1hZ5cr6uV0wcVmSgFv90QgJw6jGLKQ0j/7HWeHwyJvK4p4bFMdSZyZHbtPTLYk61vJfVwfa0OIsaLSBQBWVLJQ1bHzojppRUdobBETnOjl7Z/5GCmJwuSE5W7cJMK6/vvZdnJsQB+PT47CCOOdFgsy1Aamw6zeCMsONHc5KQ6qLkEw0fzhI2bU1IYYKYyVq1HTmVQq61nHBe1CxcUir/zMRmovNZDCyNxGcGXgjA0/0yNnMjNZLN5Zh16m1r56FjNaaFRLb2yrXY1yEr363xSaCtdusNj0ZSZCyWhQcGHhAQENCk2DAMPCrUoPKteEaevkW1wz4xIs6ksb7VsYL3l6Qrvtt/EQDTk9XVwl2myLYOsVta8qraYJZjBVkljFipqdxs++OM2tQ/9uh1QJkZG4NMxosNFSCYC2a/PF6UJ/nTk5IKoGD2SmPixUV4g032p29nKmReFqhxsiBpRH80I8z/Eg17tmINPfFxOlOyyrGq9H4BJ2pD0POwQhXjuTSnUrJSeCYrNtv+rBWFEAY0X1CLySFj2vfJGsdZSVeA86UDnsvGuVulsP1Fx5MzErRi8sQlwQJcssKYzV6/p1PSDfTFx1gKR7N7YWBGrm3tvTBXO6QxNcFGhvmusdq6nQZgZdtkDuhplTnhRVtlBfWGTln59jZZEE8t8240RUYjCAw8ICAgoEmxYRi4BVu8ZccPAfiTwVcAMMxhNzcAACAASURBVDUhTbSyXxZgs1K2x5GSsMKDWjLr5JgG7liQixKJRKrIxR2SiGc5iXRMVjhLNqbHGcm0cLoobRgoHgcWDhYp+hIlpTgWbPGVkWsBeHJYizXMk2CrYURFIWJVSbEAPnfseQC8Z/d35Iuk2MZNljlY7OLkhFa9b1S1UI/ZGWrssBZoNTma4bjKHx9KqA28RfwNO9uOLHDAMiwoK15zXPNh9BflXE4Xn4mkkwvZOK/rkMCv749cwH2npE21RQuWglRarvm7Lr4TgJe0inSzL14ittji05SLQB8fl1VVpDYx6L3qTCWizDnTMhNJTxNqh58YadF96PWqZfGuzLy7ukTltF1Xur+5U5RUl6REQtyrK6eVTAuwllhsioxGEBh4QEBAQJNiwzBwYzGmj7XCt1O+mkE0UopsMRgsClP42hlJTzo+WeNpVwbW1THJZa0SIFKbSMcCHvqLEpSwHLtmoRDjC6eeA8A1u7/a0DYlPM8UZCWxf1qS4f9Yk+JbsEXBysEtp6iysaciEQvLqz18SkPdW9XObOqHo9qurw89u1w8uZbRGWoCN2KpYsQu41o0wGz55kuIApNKFhTkyBXlOAed2MAf7hC2e1VGGHgysbAt3IKyrGjHgIa823E//sz1AFxx/uc5UmjMxnnpOyWw6PB4D6NjopQp5OQWdOovqa09UcrOHbzi1E+0vVtUGsa8L00tPcx8oDjBsYKMnQFNGBZdd73mCbW5b+nREntZSRq2tWWMa9qloPK3ByV0/omUrAAHVMEU+YUqFjY2HiwFxRu2StGMK9Niy98cbz7FST0Y065dmc2VIqMRBAYeEBAQ0KTYMAx8IcxXJGEpMLXGYVWOHJ0QHXNhurpLzM7Xnp6mT6MKk1QzcIum/OwxSXVqipJFocLWujUjjGZijqK85cRXwoQGS3H2T0vBg08dlcjLEyNyXpb8yattcsVCsov1JSQW/WhqjkG1p57OtUVtmdWGGuadaRe7+fbuEa7tlWISFol7YFzCuI9o4qNBSytrkX0FF6lmLGLwByfPA+C8jJRt3dnx1IKn16eM/207/w2APzqjIe9DojCy1UR/sZV2TYBVa+OM5zTt6k1yDk9OSdvHZtLReHbj0k+Z0xrf8EM59xPXyP6nRYJNKVuMGHeqRfa/rVvG4/v2fBOALXUKSC8Wp4oxPnlUVhe5yWpGaOkKomRhWujjNV1SCm9Polyi+YqMrFb/IvYSAO7VVenEjK4OKv0g2uyMpploVR9T2xI07BsREbNWpl2rNlkK8zYEBh4QEBDQpNhwDNy8/xEsr80yiyTUol7RYqhgqtYezX+yq22Ii5IDACSdsIjTavt+eEZshsdGxGtfXCgxUT3oeWYzM5yTMR1v/XOe1Lwtt05KcqlHJnfwkwmx9xrzntSkQdH5LIacxZeg5V0Ak4VUWXFRs19jdq2dwuyeu01Stb51853s0HwzdlXGOmXI7s/tBOCzx0RtcxRNRTqZjBREVqhiZEKu19GZHqDs9+ich76YT2aHFh6IcpY4YeDm5zhdbCenxT9qbZzGvBO6enh4SMbJ6FSG4qhs09IvbdzzlYGq428TMRaHXl1moca833XJvwLwsrZHgPJqYSmpbWvRX2xlcErs82avdhoR2douK409XTI+n9N2EIDLVd/fGSvbqnt0lfjrW0RJcnTidXI+6kMojOt5VYypMV3VWNnESS/nu5xUuBsJy2Hac2HDTeCGFnViDqlpYVIvrlVzHygeX9KAtYo7g5r18MlxCRAat4xqhWqHjd24r+55kBkNn34iL5/tnxan5Z8/IaVBJ8ZqKok0AFsWW5Wfizad5hXtUhMyO8cSsl8n5UcmRSb3wOA5jE1L/0Qmk5p6guUD6us8ocxmNnIqBTMnU5X8r6ICDkChZKkQqkPMK2uYRs7LmmPHNVnRDTtlQjCnzoXJEm2xageWJR3bGj8MwObdYm76eEoqsT9xpo+xQXO+6TZq0jo4IfaIya7GH7DmzNzaLscZHtbgFp2IPnn0ev7i3H+savfb3v0DAO6dkgfsbQMSHHZCa4DOTCdxWqN0279N1z2umVAqn7wtabknnqXO2OU4K2thZORYYVe5Io7CHhwv3Cn51V/dLbXNTd6XrDPBWpCbJXwzeemf5sUUdTyvdS9z8Wgs2dj9ar88AK/aKU7fpWR8PFsQTCgBAQEBTYoNx8DNCRbxNv3HWNTnT0qa16t2f4XuKNXs4p9DwxoQ1J8ThlecmS1vgjKzPJDbxoQ65GzZfuSMsAgLLa8XOj8XjHl39whDed+FtwJwWepEZDrJzlF3ckJD7fcPiRnhSH93JBOcK1921KGVZpna9K3KvI0RZ1qqQ8KNIRWmEpHT1VIetKeFSRpjRQNI5q1hqm1pycq2+1rEybhPw/Db6lRdMeeomTguVxZ4Zaew0qHpLOOjGjyiJhsLs7drPeEbH/bmGHzz9rsB+OMBYZA5dWYO51o4VZT93tgiv50sSb8dL4j5ZSwvv53RIKDiVBynTkxj2mYyKTsvZV+VMkILIrK0BaeLh6v6YjmwVd3Hn7k+qohjY3Rzp4zRN226C4DLU3J+LU5Ww/Pdf1axyeSlL9giDuQvDolsN5+LR/ecCQhOTMpK5WRR9n/eT4cvc1UQGHhAQEBAk2LDMXBDlETIYkfUITUwJWzn6Xw325TtZV3jzoEpL0ygv6iVtKctuKS+3XpKA3s+e+C5eGUKURDJUpyVCrMr/s4FtwFwY4uEzc/Hpixg6EheUt2eGpO+yE8mZ7PpGsZt4coRSq5s01YktU09WrjB6lEmlYWaI3nSO0p6PGPPv3bOvwBlh5rBbOC1aYIBYsrwzu0Wp9gLWx+X49F4v7ZrAYZ/3ym1H8/kWzkyICuj/JStStQpZnU1feOUrrfGmdmidRlzWoCh3nkZiuoPmC5oCtp8eXXk9dxNJlh2Vs5m3gZb6X38sNj7r7pQVh2bl2EjtjH1iDriT420R+M63S2OSKsedH5SnJUt6sRfzMr3WSnxIdydkH0kdJVVGVRu49GCwiZKlj5D7/MmDaFfTQQGHhAQENCk2HAM3NLKdqfl9ZiyQgvZzimbOZTv43mZ0UXvf1Dlg3eMijJgcFRrXs4RYm51+grjyRWtS2iKAksd0Igdc6QkDbBybzMWMFRP9aLMO6nqloymGrV0qFOTqXIYuiXQV/bclRGWZPVJ03Hps+1tso+BljZODoqdckenhHFvTQzXPQ+rdTpdTMySMjpt9uVdEvTRFbMQ98ZDp03tEEO2fXHno3w7Ldc2jyo5jNnNyBhaTjGGWnVUsc64MTv9JlVgFJWl11vlzRcqXwvzsYyrhNHSF1+ays+5zUKwMWW+pcrkWrVjdFNs8czb+sIUVfvSUqrOkl1VwVa4BdnmPpXJXpEWeeZPi5xwJREYeEBAQECTYuMxcGWOv7xNPN5/OPwqAIaMgWtJq/Fihmm/OAY1Xsrx+IyU9XpwUDTU+ck5wrsL1Trnedn3XGbQebZZSmBSTtlsQZlxVch+TTkqs3mnVFHSnhFbtRWNnpmJU4pXK29KyiZj2rbXbHsIgEM5MdTGlbHuah3iwZj0346sMPD2KMVutXLGilOYXbMS5lMwLb7G4iwJZh9NUiSlxW/nwlISomVj0n9RZXSlPtP5ZBSbMF6SYJzaQh8RGkkkthJFLhYBU3qMaIh7frJ8nWzlkF+ET2IupJ2Mg/aY2sBjdfrewgz0uEOF7LKP+9OOwMADAgICmhQNM3DnXBy4DzjmvX+1c24v8HlgE3A/8Bbvff1aUovA4YJqXfOidTXGaGW4TIv8zHQPE2q/a5QgnCoW+NLg1QAc7RcmPku9UYtKJlSr7EgIi0hoytO0vlpS+9xkallKlblwSccJAB4qCQsm5iuiJ1UbrzbGNmXenWlRFHRp2PNjhS0M2+ojirCU10xcS3OlhFFmnLy/TCMAi8R4ZeeDQLmwQV9sftZb8m4WAy2pdn1UddJnVHVw3rx7qg9L8DXp26IxE6EmHcOsdA0NIKPb7GiVFcfhuKQumM4lI3/K5ak7AGhTWmSa+GxS+s9Kn5UmKm67pPoqWqrt2GaLrjd+ViKxWzkhmtxnpsaqHO9x7a/8InTzc8Hs5js0IVxnixx/uKW1fI56Wkkduz/b8SgAWRdCMefCYhj4bwGPVbz/MPAX3vt9wBDwjpVsWEBAQEDA/Gjo0eqc2wm8CvgT4Heccw54MfBL+pNPA78P/K+lNqS2HNXdfyuRWhOXKiVQhllQJn50souxBpmBaV0fz/fyb8f2yn4mddu5bI01NmVcmd1a3hJjQu1ZYRNv3yupR01n/NFHbyA3BwOfzAn7rSzNBfOrUUxT/cCQFCiwVQkJT0YLwVrhg+6sMO3zO/sBeH2vJMm/bfQSAA6nuxmurVKmCpWMqk5Mx/y6dikqa0/7pIsBsv8kFnm5BIWAHn8oJ/ZX6zfLV7MYtYMlJ/vB6AXRedT6Jlo0XWmstmpCA0hakeNYdXxCIZfggQG5Hv09wmL36jamif8P54iO+veHXgPA1GR53MY1UdR1eyUPzI6MqHm++MQVQJ3SeysES4h218Q+oOxbqoRFIds4sBiKNjeHjb8BWJ+8c5eUf/ujoVdG5+j0u10dQ/pb0Y63LCLO42xDo3fIR4D3Uvb6bAKGvfe2bj4K7Ki3oXPuXc65+5xz9/WfWfzSNSAgICCgPhaksM65VwOnvff3O+duXOwBvPcfAz4GcPXlmbp89/7pmVnlqLqnhFG2npYmHnm5/lij2U5PtkeqjIVgWtfPnnp+uajAQhkDayIYU5k8mzqEbbanpG3GVDel5fMXZqVobUnp2de6LufwZP08KVFUXUVpLiAqz1UJS0NpLLArLex3U7fojFPxIh1q4+5IyetW1ci/fZMwnchGrXbF24+dX159WGFgU6No+00xYIn1TUlQiYVYsik+6umla1c/YyWNblRW38jVNbbeX5K2DeZbo0yBEXSlYoxyMorwE4bXSISf9clUsWbfBceE6strC27bamprQuzmve1yXkfH01HUYUe7xDtc1CoFs/emJR/MLRlZKU0zm+2uRGpl8x9NFjV7ZR27ekH12D8cF6/EDS3ie1lOgbPa0okt6Xx0js5KtsWsKMjScx2dLWjEBnEdcJNz7pWIRqwD+EugyzmXUBa+Ezi2nIbUVjMppmXwDL1VJilXU916LJfmeEEckSNJMRN01kl+BGWpVP9UW1SDcJbsrsYJ2KJ5wDvVFNHXMsF5bXKc13RJOk2Tlm3S186Yho3rzPTOXXfyR0NayaVmArcJfWRKBu83xn4GgMO5TbNq5lklj93axt/ZLomvvtchN3nRx7gye0jaqcvOHpX1Wf3OuF5qM8PUu2FtUjmTk5usKy6TiwVjLOVGmqu6eyVs+T5clOOOlCRBVXespeFjWiX1Z8a7y4nJDHqqFvb++LSkIniBVj5qBO1qOmmNS79GoeC5+LznBuXgtN4WGcvjPanoYXLBJhlTlkL4SEG0lNEkXUdWaLnIzfw2oOa3xaRXbtWx2p2QtlmA0njFsDCZ6mhBncw6PpYSum8P2jOlKW271Y8tPxCTKSEZlj+93c3vGA9owITivf+A936n934P8Ebgdu/9m4HvAb+oP3sr8LVVa2VAQEBAwCwsRx/0PuDzzrk/Bn4EfGI5DamtZnLtG6XO3ku0Os2XDl8OwOAJkT1NTKajSvKXb5OagPNVWAFhYImMVjlXqZIVbEjp+62twsp2ZsWZZMnre+Lj9MUsZap0Wzlgo35ypL74aLmSS52lMMDwoCxIvxQXp1X2r7pmVTO3GnrGsDJOzCT51gOAyPrKVVFsFVJtFrCE/XeMSgWiWVI7iGSExlSHixZIkavb9sUgGS+WHcI15qtpDfL55hkxn3Wp/O6i5AC9cQvFlvOJKSU1JndSz+PuSVmN9I+3zgpZj6WrU95e2XJo0e3v0aRZr+yR4Ka7ju4BJBlTwWSj3kwp1aaZ2uC0z3AtL+0VU9YNWUmvamlrB4s1JrQ6fVbU/790SsbHDXsOL/p8TJr3/FYx+92WvhCAgbiP+s+Sbx0ck0CuU5tkrJ5TUtau12S+VZIxb3OAPpmX8fnRQ2IynakwdxV0JXZtlxSOyPlgOlkIi5rAvfd3AHfo/weB5658kwICAgICGsGGCKW/Kp2as2LzhJen/D8nL5UPlJHkp5IcGpMahw/0SCrMjJOUrJ3KfIwB9WjV8G3ZUeiT3Vy9SeyGaXXuGevs1HSXv9ghK4AtVWy7sTSkxnb7i7siueBCSHxmk/5XVupENvAapNWpaIn1AWILuPzGShaUoeH4hToBIqVqBl5SC5uVMUsuIaBiiyZ0ak9NE2+R/RTHq4edOR0fPCXXcXjmRQDsaR3kWa2S6OrclDj3zKZ+KC9ivU8fkeIaJ7Vc2fRUMgoYslqbHe1yTV+0WeSQVj19KUmzLEFVW4uw+SlaInu22davz4xUbWsrpwuTcg7P6z4UObwvSFavzCz4p69VXkdaZNtiRfCP1+PtbRVfwURp8UzVzqcnXp087nCyRFGTnBkTtzqrn+6/DoDkZkkd/Cx15ne6uUu7mT+ovyj32Z0TssoanNC6mxUySXOif/m4rKxv3PfEos/rbENYowQEBAQ0KTYEA4e5Kzb/a0490vq0jx45JTimifv/LinMoLhdAmlelj1ZtQ+zQf7u9lv54ZRIos5TRmcYVQnbNRkR05jNc87ERPOgsjzVTK2krQbGQIZfL8wufXsH1/6KMG8rklvbN8aEF8OIrdviDSRwsmRWMQteWUYos/X9f9j5A/5gVBKTjU0o81WmbEFVE2pzfSInya2Ot3ZwX0KCZGxVYHJEU2IYey9VBmZFxZml/Rf2yrV+UZvYnXuXURjAgoCipFaU0ztYmlpLWdxWQ4+sL96hKiaYbT82W/jbd4r88/cHNfhnolzGLq2pgdsSck901UsM1SCs5F1nUlapiWSBYkyvt9raJ4aFYd9d2g3AyMzLAHjzVikzd1HqVNT27pqUs0Masn8gLyvMg1NiT58l9QxYEgIDDwgICGhSbBgGPhe2qo2uNyM2wUMaMj49lo5SXx4bEWXKI91S5PeqtLDoNmVLleqNfUmxq1kq2urwcEhSbT9fDtLxQhTuPpdSOL1J02uqCuZPf+cTkZZ7rlXJUhBXVmrsum4wiH5kCpVMTJMwzZkvd2H0RsEsw2xqlWs5FlO9sikr9NXr1Sgo2x4tZcvBRaajt4CgeVIgOFWddGlpuH2torU+VzXPi7F9L4iKItH3jOwB4BfaH6r700Z02vabzToGIlt7LBOVoOvS2IS9aTmvbGzpK6Qe1bdvU7t9a8t0uUi3KZXUFp4bl0Clh2ck6PpDA7I6uKhPGPgbttzLnuSA7ln2e7ywBYDPnBBfxVODwsArtfpOfSOdHXJ93rdHVGW15fkCZiMw8ICAgIAmxYZn4Bbd+Mub/xWAgdxLAXhiagtebaYjI+LRvvvMHgAuyIgNPJYRfexs3fbqwuyYb9nxQ/5k8BWA2jDnwfsu/jYAV6YHGyqvtlhktX7ZtpQwrUwqz1RtUiIltzPKvHIlYWJTXtngMpIYJV2xnMTfaENtahxj4sqyi5V67rlSH9SkPEhn82ztkjDtl28Vm/dN7ZL61gogrzQsfXCnFv1dSf1yrCIi02zf79wj9vEXZyUBVnIZpcasT97UdQ8Aw/ksd+QlwdXEtMYBWKqFaV0h2eu4jI/9U+KnOJNrpSWhJRC16IilqbXShfmJmlQWDrK6qn7/Rd8C4Ip0/fJ8AbMRGHhAQEBAk2LDM3CzCV6UkhSTl3ZKQp1TY+0MnxFbphXnffqkiLw/XpQEUU9s3grA27rEW16rCljtNu9IDNGhqWanhpW91miUN3eK+uSilJzXarEOKyp7iapsWlJXMFTzG7PXG1OuLSq7XMtxuyodrHhBXiMXZxXVMLPyfAnHzKafqbZ337D9IK/tkvZemNTiAbGV82uYiidixh5iUbIsYZ2pJaSrrYWpXVq0GERLZ45dPXLFnqMry12J5dvybVW6NyExBb/S+wMOjoti5AlV10Qa9Fq/gwWJqpLq0JG+KCWsRfX6Gj9H7T5cusSWDlnhmf08MO/GseEncIPJ+l7XfR8Ap6Y7uGdSZE35MRloJkc7fEIG4L/pRPSqDpFt7WVtEXOlKHz7tE7YZvaJa63KF2yRUOquqKbk6uQ+tkyC5iBtT01HZgdfL6x+hZFxRfoy8rDa3C1tGE6L5GxyVCaRWVXbHdGNb9VsLOFRR6s8DKx/93WIQ+/Gjsd5tmaH7FxJZ2UNkvHqvOArjU2aCXJbVrP2JfK855zvAKvj3LOH2+7EBO/ffQsA//fMLwBwXIuV1gZgRYgmafD5BseSbpJunYmunaWqaDRgLiCYUAICAgKaFk3DwG2pd2FSEx21neSRrJhIRqx+oLJbM6mYA6U2T/NaoSuWY5PKH49lRepold97Nbf4xS0S/m9Jm1a/TcL0r+w+wsHTslLJz1Q/x82JaSlqV6ImYVeswHUdEj5+bYckK7pnTEw0xyelb05OtAPloJ2Y89H/xrTffo44s3ckxJyQ1JSjXVGisRLJNWBwUTKwCgZuJqKVYEUm73vbFnFYDpeyXKZmxM3x1VtZ9MZbuUTzsf/hPkkw+t7CvwPgjJfjlhZwyDcCW1Ft7RrlHX0SsGZig4DGERh4QEBAQJOi6R55GWWDL2h7nP09ErhzNCk2usmZauZlrM0SBMHcSXdWA32xAi/ueRwoS8xGNJ3m27YIk7wkJQmJliMFawQW2mxMf3NqlLas9M+whTWrYy6TEHZkBStWQn7ZG0vxujZJTGWh5i9sERlcv66QLB1rqY4ML0ryFK+udlPmIKtzba1Wq+HeqQuAChu4LxfHMCfmSqzzeuNyPsa6s7HRVR8j5WNL316SEl/FH1/4VQA+fEgksSc0cdiMFmOY08lZgdik9k2LpmdQX8aHzv0nzlUHalssOC8Xi8DAAwICApoUTcfAjQ3uSYxHSfF3bbO0msLkbhmU8mRv3az1INcpJLczluK1bWL3vaFF1CatqoyxwJreVbRn1kNS085elD4RldEaU0VMizJyK/1lpcAgy3JRKeGrlXPOVgfVu15ru3oy5m21Wq24RsdLJUjs1GBH9NuYsvEJrS+ZXAFliqUv2Bwv9/1a14a0VY4F1vyPff8AwCMz4nv6zPHnA+VUFmPjLRSnq/0lbkLepwd1BfiQBlz9J9lnzicXVQouoBqBgQcEBAQ0KZqOgRt6Ygl+qf1g1Wc5LTzwwh0nqj5fryd8NpYiq3bLpRSCXQ2U9b5DXNAl+luzefcp8/6P226X9/F5jJo/pahl3o9+SAoQWJm76ZOS6ta/SjXLFV1kleVXAhupEvvmKMGWvN8SF+XUZXu+BMC/TJ4PwN8+fR0TU7IKnpnU1cionMeeL8sqOd8rK4pT/yzh933vHmO1Yh/OBmycURIQEBAQsCg0LQOvp4xYW2tyc6Mv7nnv1lsB6C9V27gvUq392WybNJu3MW9D7JelOETptCifKDkSWjhisiRMsnMZ6V2bATYueqPTFD/Pj7bs4shENwCDUzqmvivpY2c2yzaFFtlornKBAYtDYOABAQEBTYqmZeABy0NvvDViUPt8bV7XtUm7u5FhDNGYuL3fnRFb7hfyUnh38ERnVIzj2VlJMhVfrQQpGxTmK3nvlu9wsijM++Gc2Ljv+PULAXj0SxcB5X6cq1xgo6jV5xtWsghKMyAw8ICAgIAmRWDgAcsqWvzThojBKUN8x7vlNeflVhlWf8HnS1dF22SSlo9FdPNrVThko6DSJr5H/QHXpI8AcGXLIQDi7/5W1TbLYcr3T8/M0udHNvVlMvtmQ5jAAwLqoHYCOFEQieVnRsQkMKVh5CQ8rSlZzmdDOtRZ8sfnpldukV8p8ayVd9pEbg/cswXBhBIQEBDQpAgMPCCgAQxqoqofnJF6kTOaACyWKnJuuzg2WzW17dnMwNcCd9585Sx559kqSwwMPCAgIKBJERh4QEADuDQlybSeGZYAHq91IH3ck44Xqn4TsDowv8RD//mvedn2KwC49fj+ml+dHc5LQ2DgAQEBAU0K5/3aJSxyzvUDE8DAmh20MfQS2tQINmKbYGO2K7SpMYQ2NYbd3vu+2g/XdAIHcM7d572/ek0PugBCmxrDRmwTbMx2hTY1htCm5SGYUAICAgKaFGECDwgICGhSrMcE/rF1OOZCCG1qDBuxTbAx2xXa1BhCm5aBNbeBBwQEBASsDIIJJSAgIKBJESbwgICAgCbFmk3gzrmXO+cOOOeecs69f62OW9OGc5xz33POPeqce8Q591v6eY9z7jvOuSf1tXsd2hZ3zv3IOfcNfb/XOXe39tc/OOfWPMTMOdflnPuic+5x59xjzrlr17uvnHO/rdfux865m51zmbXuK+fcJ51zp51zP674rG6/OMH/0LY95Jy7co3b9d/1+j3knPuKc66r4rsPaLsOOOdetlZtqvjud51z3jnXq+/XpK/mapNz7t3aV4845/6s4vNV76clw3u/6n9AHHgaOBeJdX0QuGQtjl3Tjm3Alfp/O/AEcAnwZ8D79fP3Ax9eh7b9DvD3wDf0/ReAN+r/fwP8+jq06dPAO/X/FNC1nn0F7AB+ArRU9NHb1rqvgBcAVwI/rvisbr8ArwS+CTjgGuDuNW7XS4GE/v/hinZdovdhGtir92d8Ldqkn58D3AocBnrXsq/m6KcXAd8F0vp+81r205LPZU0OAtcCt1a8/wDwgXU/efga8BLgALBNP9sGHFjjduwEbgNeDHxDB/BAxY1X1X9r1KZOnSxdzefr1lc6gR8BepA8Pt8AXrYefQXsqZkA6vYL8FHgTfV+txbtqvnuF4DP6f9V96BOpteuVZuALwKXA4cqJvA166s61+8LwM/V+d2a9dNS/tbKhGI3nuGofrZuijl6uwAAAvJJREFUcM7tAZ4N3A1s8d6f0K9OAlvWuDkfAd4LlPT9JmDYe2/5Sdejv/YC/cDfqWnn4865Vtaxr7z3x4D/D3gGOAGMAPez/n0Fc/fLRhr7b0cYLqxju5xzPw8c894/WPPVevbVBcANaor7F+fcczZAmxbEWenEdM61AV8C3uO9H638zstjds20lc65VwOnvff3r9UxG0QCWWb+L+/9s5EcNlW+i3Xoq27g55GHy3agFXj5Wh2/Uax1vzQC59wHgQLwuXVuRxb4r8DvrWc76iCBrOyuAf4L8AXn3IavTr1WE/gxxOZl2KmfrTmcc0lk8v6c9/7L+vEp59w2/X4bcHoNm3QdcJNz7hDwecSM8pdAl3PO0v2uR38dBY567+/W919EJvT17KufA37ive/33ueBLyP9t959BXP3y7qPfefc24BXA2/Wh8t6tus85AH8oI75ncADzrmt69gmkPH+ZS+4B1kN965zmxbEWk3g9wLnq1ogBbwR+PoaHTuCPlE/ATzmvf/ziq++DrxV/38rYhtfE3jvP+C93+m934P0y+3e+zcD3wN+cT3apO06CRxxzl2oH/0s8Cjr2FeI6eQa51xWr6W1aV37SjFXv3wd+GVVWFwDjFSYWlYdzrmXI+a5m7z3kzXtfaNzLu2c2wucD9yz2u3x3j/svd/svd+jY/4oIiw4yfr21VcRRybOuQsQp/0A69RPDWOtjO2Ih/kJxIv7wfUw+APXI0vbh4D9+vdKxOZ8G/Ak4onuWaf23UhZhXIuMlCeAv4R9Y6vcXuuAO7T/voq0L3efQX8AfA48GPgs4g6YE37CrgZscHnkQnoHXP1C+KQ/isd9w8DV69xu55CbLg23v+m4vcf1HYdAF6xVm2q+f4QZSfmmvTVHP2UAv63jqsHgBevZT8t9S+E0gcEBAQ0Kc5KJ2ZAQEDATwPCBB4QEBDQpAgTeEBAQECTIkzgAQEBAU2KMIEHBAQENCnCBB4QEBDQpAgTeEBAQECT4v8A/6NOiLRUEQIAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(cv2.imread(directory+images[0], 0).astype(np.float32)/255.)\n",
    "plt.title(labels[0])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "charset = '0123456789+-*()'\n",
    "num_classes = len(charset) + 2\n",
    "encode_maps = {}\n",
    "decode_maps = {}\n",
    "for i, char in enumerate(charset, 1):\n",
    "    encode_maps[char] = i\n",
    "    decode_maps[i] = char\n",
    "\n",
    "SPACE_INDEX = 0\n",
    "SPACE_TOKEN = ''\n",
    "encode_maps[SPACE_TOKEN] = SPACE_INDEX\n",
    "decode_maps[SPACE_INDEX] = SPACE_TOKEN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "image_height = 60\n",
    "image_width = 240\n",
    "image_channel = 1\n",
    "max_stepsize = 128\n",
    "num_hidden = 256\n",
    "epoch = 20\n",
    "batch_size = 128\n",
    "initial_learning_rate = 1e-3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pad_second_dim(x, desired_size):\n",
    "    padding = tf.tile([[0]], tf.stack([tf.shape(x)[0], desired_size - tf.shape(x)[1]], 0))\n",
    "    return tf.concat([x, padding], 1)\n",
    "\n",
    "class Model:\n",
    "    def __init__(self):\n",
    "        self.X = tf.placeholder(tf.float32, [None, image_height, image_width, image_channel])\n",
    "        self.Y = tf.sparse_placeholder(tf.int32)\n",
    "        self.SEQ_LEN = tf.placeholder(tf.int32, [None])\n",
    "        self.label = tf.placeholder(tf.int32, [None, None])\n",
    "        self.Y_seq_len = tf.placeholder(tf.int32, [None])\n",
    "        batch_size = tf.shape(self.X)[0]\n",
    "        filters = [64, 128, 128, max_stepsize]\n",
    "        strides = [1, 2]\n",
    "        x = self.conv2d(self.X, 'cnn-1', 3, 1, filters[0], strides[0])\n",
    "        x = self.batch_norm('bn1', x)\n",
    "        x = self.leaky_relu(x, 0.01)\n",
    "        x = self.max_pool(x, 2, strides[1])\n",
    "        x = self.conv2d(x, 'cnn-2', 3, filters[0], filters[1], strides[0])\n",
    "        x = self.batch_norm('bn2', x)\n",
    "        x = self.leaky_relu(x, 0.01)\n",
    "        x = self.max_pool(x, 2, strides[1])\n",
    "        x = self.conv2d(x, 'cnn-3', 3, filters[1], filters[2], strides[0])\n",
    "        x = self.batch_norm('bn3', x)\n",
    "        x = self.leaky_relu(x, 0.01)\n",
    "        x = self.max_pool(x, 2, strides[1])\n",
    "        x = self.conv2d(x, 'cnn-4', 3, filters[2], filters[3], strides[0])\n",
    "        x = self.batch_norm('bn4', x)\n",
    "        x = self.leaky_relu(x, 0.01)\n",
    "        x = self.max_pool(x, 2, strides[1])\n",
    "        x = tf.reshape(x, [batch_size, -1, filters[3]])\n",
    "        x = tf.transpose(x, [0, 2, 1])\n",
    "        x = tf.reshape(x, [batch_size, filters[3], 4 * 15])\n",
    "        cell = tf.contrib.rnn.LSTMCell(num_hidden)\n",
    "        cell1 = tf.contrib.rnn.LSTMCell(num_hidden)\n",
    "        stack = tf.contrib.rnn.MultiRNNCell([cell, cell1])\n",
    "        outputs, _ = tf.nn.dynamic_rnn(stack, x, self.SEQ_LEN, dtype=tf.float32)\n",
    "        outputs = tf.reshape(outputs, [-1, num_hidden])\n",
    "        self.logits = tf.layers.dense(outputs, num_classes)\n",
    "        shape = tf.shape(x)\n",
    "        self.logits = tf.reshape(self.logits, [shape[0], -1, num_classes])\n",
    "        self.logits = tf.transpose(self.logits, (1, 0, 2))\n",
    "        self.global_step = tf.Variable(0, trainable=False)\n",
    "        self.loss = tf.nn.ctc_loss(labels=self.Y,\n",
    "                                   inputs=self.logits,\n",
    "                                   sequence_length=self.SEQ_LEN)\n",
    "        self.cost = tf.reduce_mean(self.loss)\n",
    "        self.optimizer = tf.train.AdamOptimizer(learning_rate=initial_learning_rate).minimize(self.cost)\n",
    "        self.decoded, self.log_prob = tf.nn.ctc_beam_search_decoder(self.logits,\n",
    "                                                                    self.SEQ_LEN,\n",
    "                                                                    merge_repeated=False)\n",
    "        decoded = tf.to_int32(self.decoded[0])\n",
    "        self.dense_decoded = tf.sparse_tensor_to_dense(decoded)\n",
    "        \n",
    "        preds = self.dense_decoded[:, :tf.reduce_max(self.Y_seq_len)]\n",
    "        masks = tf.sequence_mask(self.Y_seq_len, tf.reduce_max(self.Y_seq_len), dtype=tf.float32)\n",
    "        preds = pad_second_dim(preds, tf.reduce_max(self.Y_seq_len))\n",
    "        y_t = tf.cast(preds, tf.int32)\n",
    "        self.prediction = tf.boolean_mask(y_t, masks)\n",
    "        mask_label = tf.boolean_mask(self.label, masks)\n",
    "        self.mask_label = mask_label\n",
    "        correct_pred = tf.equal(self.prediction, mask_label)\n",
    "        correct_index = tf.cast(correct_pred, tf.float32)\n",
    "        self.accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))\n",
    "        \n",
    "        \n",
    "    def conv2d(self, x, name, filter_size, channel_in, channel_out, strides):\n",
    "        with tf.variable_scope(name):\n",
    "            return tf.layers.conv2d(x, channel_out, filter_size, strides, padding='SAME')\n",
    "        \n",
    "    \n",
    "    def batch_norm(self, name, x):\n",
    "        with tf.variable_scope(name):\n",
    "            params_shape = [x.get_shape()[-1]]\n",
    "            beta = tf.get_variable('beta', params_shape, tf.float32,\n",
    "                                   initializer=tf.constant_initializer(0.0, tf.float32))\n",
    "            gamma = tf.get_variable('gamma', params_shape, tf.float32,\n",
    "                                    initializer=tf.constant_initializer(1.0, tf.float32))\n",
    "            mean, variance = tf.nn.moments(x, [0, 1, 2], name='moments')\n",
    "            x_bn = tf.nn.batch_normalization(x, mean, variance, beta, gamma, 0.001)\n",
    "            x_bn.set_shape(x.get_shape())\n",
    "            return x_bn\n",
    "        \n",
    "    def leaky_relu(self, x, leak=0):\n",
    "        return tf.where(tf.less(x, 0.0), leak * x, x, name='leaky_relu')\n",
    "    \n",
    "    def max_pool(self, x, size, strides):\n",
    "        return tf.nn.max_pool(x, \n",
    "                              ksize=[1, size, size, 1],\n",
    "                              strides=[1, strides, strides, 1],\n",
    "                              padding='SAME',\n",
    "                              name='max_pool')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sparse_tuple_from_label(sequences, dtype=np.int32):\n",
    "    indices, values = [], []\n",
    "    for n, seq in enumerate(sequences):\n",
    "        indices.extend(zip([n] * len(seq), range(len(seq))))\n",
    "        values.extend(seq)\n",
    "    indices = np.asarray(indices, dtype=np.int64)\n",
    "    values = np.asarray(values, dtype=dtype)\n",
    "    shape = np.asarray([len(sequences), np.asarray(indices).max(0)[1] + 1], dtype=np.int64)\n",
    "    return indices, values, shape\n",
    "\n",
    "\n",
    "def pad_sentence_batch(sentence_batch, pad_int):\n",
    "    padded_seqs = []\n",
    "    seq_lens = []\n",
    "    max_sentence_len = max([len(sentence) for sentence in sentence_batch])\n",
    "    for sentence in sentence_batch:\n",
    "        padded_seqs.append(sentence + [pad_int] * (max_sentence_len - len(sentence)))\n",
    "        seq_lens.append(len(sentence))\n",
    "    return padded_seqs, seq_lens"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Logging before flag parsing goes to stderr.\n",
      "W0829 22:51:45.737936 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:69: conv2d (from tensorflow.python.layers.convolutional) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use `tf.keras.layers.Conv2D` instead.\n",
      "W0829 22:51:45.743227 139691927603008 deprecation.py:506] From /home/husein/.local/lib/python3.6/site-packages/tensorflow/python/ops/init_ops.py:1251: calling VarianceScaling.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "W0829 22:51:45.988447 139691927603008 deprecation.py:506] From <ipython-input-7-87943060143a>:76: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "W0829 22:51:46.013294 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:85: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.where in 2.0, which has the same broadcast rule as np.where\n",
      "W0829 22:51:46.680723 139691927603008 lazy_loader.py:50] \n",
      "The TensorFlow contrib module will not be included in TensorFlow 2.0.\n",
      "For more information, please see:\n",
      "  * https://github.com/tensorflow/community/blob/master/rfcs/20180907-contrib-sunset.md\n",
      "  * https://github.com/tensorflow/addons\n",
      "  * https://github.com/tensorflow/io (for I/O related ops)\n",
      "If you depend on functionality not listed there, please file an issue.\n",
      "\n",
      "W0829 22:51:46.682112 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:34: LSTMCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "This class is equivalent as tf.keras.layers.LSTMCell, and will be replaced by that in Tensorflow 2.0.\n",
      "W0829 22:51:46.683474 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:36: MultiRNNCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "This class is equivalent as tf.keras.layers.StackedRNNCells, and will be replaced by that in Tensorflow 2.0.\n",
      "W0829 22:51:46.684638 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:37: dynamic_rnn (from tensorflow.python.ops.rnn) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `keras.layers.RNN(cell)`, which is equivalent to this API\n",
      "W0829 22:51:47.023829 139691927603008 deprecation.py:506] From /home/husein/.local/lib/python3.6/site-packages/tensorflow/python/ops/rnn_cell_impl.py:961: calling Zeros.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "W0829 22:51:47.727965 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:39: dense (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.dense instead.\n",
      "W0829 22:51:49.237528 139691927603008 deprecation.py:323] From <ipython-input-7-87943060143a>:52: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use `tf.cast` instead.\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "sess = tf.InteractiveSession()\n",
    "model = Model()\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100000/100000 [02:43<00:00, 610.59it/s]\n"
     ]
    }
   ],
   "source": [
    "from tqdm import tqdm\n",
    "\n",
    "X, Y = [], []\n",
    "for i in tqdm(range(len(images))):\n",
    "    img = images[i]\n",
    "    X.append(imresize(cv2.imread(directory+img, 0).astype(np.float32)/255., (image_height,image_width)))\n",
    "    Y.append([SPACE_INDEX if labels[0] == SPACE_TOKEN else encode_maps[c] for c in labels[i]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size = 0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:21<00:00,  1.37s/it, accuracy=0.594, cost=7.13] \n",
      "minibatch loop: 100%|██████████| 157/157 [03:32<00:00,  1.10s/it, accuracy=0.59, cost=7.28] \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 1, training avg loss 13.664520, training avg acc 0.256896\n",
      "epoch 1, testing avg loss 7.003703, testing avg acc 0.596915\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:16<00:00,  1.37s/it, accuracy=0.966, cost=0.794]\n",
      "minibatch loop: 100%|██████████| 157/157 [03:28<00:00,  1.06s/it, accuracy=0.967, cost=0.917]\n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 2, training avg loss 3.353983, training avg acc 0.815715\n",
      "epoch 2, testing avg loss 0.913711, testing avg acc 0.958989\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:08<00:00,  1.36s/it, accuracy=0.994, cost=0.111] \n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.03s/it, accuracy=0.967, cost=0.26] \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 3, training avg loss 0.431414, training avg acc 0.981401\n",
      "epoch 3, testing avg loss 0.203769, testing avg acc 0.988942\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:10<00:00,  1.35s/it, accuracy=0.999, cost=0.0418]\n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.05s/it, accuracy=0.976, cost=0.11]  \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 4, training avg loss 0.146375, training avg acc 0.993252\n",
      "epoch 4, testing avg loss 0.130219, testing avg acc 0.992678\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:07<00:00,  1.35s/it, accuracy=0.999, cost=0.0442]\n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.04s/it, accuracy=0.976, cost=0.11]  \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 5, training avg loss 0.096891, training avg acc 0.995104\n",
      "epoch 5, testing avg loss 0.119220, testing avg acc 0.992331\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:08<00:00,  1.35s/it, accuracy=0.996, cost=0.0601]\n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.07s/it, accuracy=0.991, cost=0.218] \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 6, training avg loss 0.085956, training avg acc 0.995440\n",
      "epoch 6, testing avg loss 0.136504, testing avg acc 0.992477\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:07<00:00,  1.35s/it, accuracy=1, cost=0.0201]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.04s/it, accuracy=1, cost=0.0386]    \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 7, training avg loss 0.065135, training avg acc 0.996399\n",
      "epoch 7, testing avg loss 0.076356, testing avg acc 0.995863\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:07<00:00,  1.35s/it, accuracy=1, cost=0.0186]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.06s/it, accuracy=1, cost=0.0212]    \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 8, training avg loss 0.058813, training avg acc 0.996647\n",
      "epoch 8, testing avg loss 0.079129, testing avg acc 0.995560\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:08<00:00,  1.36s/it, accuracy=1, cost=0.0132]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:27<00:00,  1.05s/it, accuracy=1, cost=0.0707]    \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 9, training avg loss 0.052637, training avg acc 0.996959\n",
      "epoch 9, testing avg loss 0.067974, testing avg acc 0.996060\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:18<00:00,  1.42s/it, accuracy=1, cost=0.0104]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:33<00:00,  1.09s/it, accuracy=0.995, cost=0.0445]\n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 10, training avg loss 0.051642, training avg acc 0.997049\n",
      "epoch 10, testing avg loss 0.045224, testing avg acc 0.997184\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:27<00:00,  1.39s/it, accuracy=1, cost=0.0119]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:31<00:00,  1.07s/it, accuracy=0.939, cost=0.321] \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 11, training avg loss 0.037941, training avg acc 0.997852\n",
      "epoch 11, testing avg loss 0.110841, testing avg acc 0.993028\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:29<00:00,  1.37s/it, accuracy=0.999, cost=0.0183]\n",
      "minibatch loop: 100%|██████████| 157/157 [03:33<00:00,  1.10s/it, accuracy=1, cost=0.0266]    \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 12, training avg loss 0.049097, training avg acc 0.997056\n",
      "epoch 12, testing avg loss 0.052734, testing avg acc 0.996672\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:25<00:00,  1.38s/it, accuracy=0.999, cost=0.017]  \n",
      "minibatch loop: 100%|██████████| 157/157 [03:31<00:00,  1.08s/it, accuracy=0.995, cost=0.127] \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 13, training avg loss 0.027234, training avg acc 0.998494\n",
      "epoch 13, testing avg loss 0.101270, testing avg acc 0.994909\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:24<00:00,  1.39s/it, accuracy=0.999, cost=0.039] \n",
      "minibatch loop: 100%|██████████| 157/157 [03:31<00:00,  1.06s/it, accuracy=1, cost=0.0205]    \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 14, training avg loss 0.036998, training avg acc 0.997947\n",
      "epoch 14, testing avg loss 0.048051, testing avg acc 0.997119\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:24<00:00,  1.38s/it, accuracy=1, cost=0.00443]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:32<00:00,  1.10s/it, accuracy=0.995, cost=0.111] \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 15, training avg loss 0.029729, training avg acc 0.998163\n",
      "epoch 15, testing avg loss 0.045602, testing avg acc 0.997220\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:22<00:00,  1.41s/it, accuracy=0.996, cost=0.035]  \n",
      "minibatch loop: 100%|██████████| 157/157 [03:32<00:00,  1.07s/it, accuracy=1, cost=0.0063]    \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 16, training avg loss 0.028113, training avg acc 0.998413\n",
      "epoch 16, testing avg loss 0.047610, testing avg acc 0.997440\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [14:06<00:00,  1.33s/it, accuracy=1, cost=0.00107]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:22<00:00,  1.01s/it, accuracy=0.995, cost=0.165]  \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 17, training avg loss 0.028695, training avg acc 0.998254\n",
      "epoch 17, testing avg loss 0.028516, testing avg acc 0.998482\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [13:35<00:00,  1.31s/it, accuracy=1, cost=0.00584]    \n",
      "minibatch loop: 100%|██████████| 157/157 [03:20<00:00,  1.00s/it, accuracy=1, cost=0.00128]   \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 18, training avg loss 0.020355, training avg acc 0.998839\n",
      "epoch 18, testing avg loss 0.033305, testing avg acc 0.998084\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [13:35<00:00,  1.31s/it, accuracy=0.998, cost=0.0693] \n",
      "minibatch loop: 100%|██████████| 157/157 [03:19<00:00,  1.02s/it, accuracy=1, cost=0.00685]   \n",
      "minibatch loop:   0%|          | 0/625 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 19, training avg loss 0.031560, training avg acc 0.998207\n",
      "epoch 19, testing avg loss 0.060350, testing avg acc 0.996566\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "minibatch loop: 100%|██████████| 625/625 [13:33<00:00,  1.29s/it, accuracy=1, cost=0.000778]   \n",
      "minibatch loop: 100%|██████████| 157/157 [03:19<00:00,  1.01it/s, accuracy=0.995, cost=0.054]  "
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 20, training avg loss 0.016528, training avg acc 0.999112\n",
      "epoch 20, testing avg loss 0.019961, testing avg acc 0.998736\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "for e in range(epoch):\n",
    "    pbar = tqdm(\n",
    "        range(0, len(train_X), batch_size), desc = 'minibatch loop')\n",
    "    train_loss, train_acc, test_loss, test_acc = [], [], [], []\n",
    "    total_lost, total_acc = 0, 0\n",
    "    for i in pbar:\n",
    "        index = min(i + batch_size, len(train_X))\n",
    "        batch_x = train_X[i : index]\n",
    "        batch_x = np.array(batch_x).reshape((len(batch_x), image_height, image_width,image_channel))\n",
    "        y = train_Y[i : index]\n",
    "        batch_y = sparse_tuple_from_label(y)\n",
    "        batch_label, batch_length = pad_sentence_batch(y, 0)\n",
    "        batch_len = np.asarray([max_stepsize for _ in [1]*len(batch_x)], dtype=np.int64)\n",
    "        feed = {model.X: batch_x,\n",
    "                model.Y: batch_y,\n",
    "                model.SEQ_LEN: batch_len,\n",
    "               model.label: batch_label,\n",
    "               model.Y_seq_len: batch_length}\n",
    "        accuracy, loss, _ = sess.run([model.accuracy,model.cost,model.optimizer],\n",
    "                                    feed_dict = feed)\n",
    "        train_loss.append(loss)\n",
    "        train_acc.append(accuracy)\n",
    "        pbar.set_postfix(cost = loss, accuracy = accuracy)\n",
    "        \n",
    "    pbar = tqdm(\n",
    "        range(0, len(test_X), batch_size), desc = 'minibatch loop')\n",
    "    for i in pbar:\n",
    "        index = min(i + batch_size, len(test_X))\n",
    "        batch_x = test_X[i : index]\n",
    "        batch_x = np.array(batch_x).reshape((len(batch_x), image_height, image_width,image_channel))\n",
    "        y = test_Y[i : index]\n",
    "        batch_y = sparse_tuple_from_label(y)\n",
    "        batch_label, batch_length = pad_sentence_batch(y, 0)\n",
    "        batch_len = np.asarray([max_stepsize for _ in [1]*len(batch_x)], dtype=np.int64)\n",
    "        feed = {model.X: batch_x,\n",
    "                model.Y: batch_y,\n",
    "                model.SEQ_LEN: batch_len,\n",
    "               model.label: batch_label,\n",
    "               model.Y_seq_len: batch_length}\n",
    "        accuracy, loss = sess.run([model.accuracy,model.cost],\n",
    "                                    feed_dict = feed)\n",
    "\n",
    "        test_loss.append(loss)\n",
    "        test_acc.append(accuracy)\n",
    "        pbar.set_postfix(cost = loss, accuracy = accuracy)\n",
    "    \n",
    "    print('epoch %d, training avg loss %f, training avg acc %f'%(e+1,\n",
    "                                                                 np.mean(train_loss),np.mean(train_acc)))\n",
    "    print('epoch %d, testing avg loss %f, testing avg acc %f'%(e+1,\n",
    "                                                              np.mean(test_loss),np.mean(test_acc)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "decoded = sess.run(model.dense_decoded, feed_dict = {model.X: batch_x[:1],\n",
    "                                          model.SEQ_LEN: batch_len[:1]})\n",
    "plt.imshow(batch_x[0][:,:,0])\n",
    "decoded = ''.join([decode_maps[i] for i in decoded[0]])\n",
    "actual = ''.join([decode_maps[i] for i in y[0]])\n",
    "plt.title('predict: %s, actual: %s'%(decoded, actual))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
